<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" lang="zh" xml:lang="zh">
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>指南: 泛化关系</title>
<meta content="Guideline" name="uma.type">
<meta content="generalization" name="uma.name">
<meta content="泛化关系" name="uma.presentationName">
<meta name="element_type" content="other">
<meta content="description" name="filetype">
<meta name="role" content="">
<link type="text/css" href="./../../../css/default.css" rel="StyleSheet">
<script language="JavaScript" type="text/javascript" src="./../../../scripts/ContentPageResource.js"></script><script language="JavaScript" type="text/javascript" src="./../../../scripts/ContentPageSection.js"></script><script language="JavaScript" type="text/javascript" src="./../../../scripts/ContentPageSubSection.js"></script><script language="JavaScript" type="text/javascript" src="./../../../scripts/ContentPageToolbar.js"></script><script language="JavaScript" type="text/javascript" src="./../../../scripts/contentPage.js"></script><script language="JavaScript" type="text/javascript">
					var backPath = './../../../';
					var imgPath = './../../../images/';
					var nodeInfo=[{view: "view:_LVCagP5WEdmAzesbYywanQ", path: ["_LVCagP5WEdmAzesbYywanQ", "_zRigkAILEdq-_NKqZM1EhA", "_qwxC8N7YEdmjRZts2c4ZjQ", "{DB21F5EF-810B-4994-B120-79FA8774FA9D}", "1.839540980397304E-305"]}, {view: "view:_LVCagP5WEdmAzesbYywanQ", path: ["_LVCagP5WEdmAzesbYywanQ", "_zRigkAILEdq-_NKqZM1EhA", "_QV4x0AISEdqTna4sZVFRow", "_kjFBYN7HEdm8G6yT7-Wdqw", "{8CDAEAD4-5E84-4F50-87FD-3240ED047DE7}", "1.839540980397304E-305"]}, {view: "view:_FCx1oN7CEdmsEI4YDGX2ag", path: ["_FCx1oN7CEdmsEI4YDGX2ag", "_f6_YwN7DEdmsEI4YDGX2ag", "_qwxC8N7YEdmjRZts2c4ZjQ", "{DB21F5EF-810B-4994-B120-79FA8774FA9D}", "1.839540980397304E-305"]}, {view: "view:_FCx1oN7CEdmsEI4YDGX2ag", path: ["_FCx1oN7CEdmsEI4YDGX2ag", "_Jvt1cAIaEdqEutyfYo0quQ", "_EOvXUN7HEdm8G6yT7-Wdqw", "_kjFBYN7HEdm8G6yT7-Wdqw", "{8CDAEAD4-5E84-4F50-87FD-3240ED047DE7}", "1.839540980397304E-305"]}, {view: "view:_FCx1oN7CEdmsEI4YDGX2ag", path: ["_FCx1oN7CEdmsEI4YDGX2ag", "_Jvt1cAIaEdqEutyfYo0quQ", "_jijhYAIaEdqEutyfYo0quQ", "_mTMIkN7REdmjRZts2c4ZjQ", "{8CDAEAD4-5E84-4F50-87FD-3240ED047DE7}", "1.839540980397304E-305"]}, {view: "view:_FCx1oN7CEdmsEI4YDGX2ag", path: ["_FCx1oN7CEdmsEI4YDGX2ag", "_jD8dUAIbEdqEutyfYo0quQ", "_2ClPcDIcEdqDs_9ORT1Rig", "1.839540980397304E-305"]}];
					contentPage.preload(imgPath, backPath, nodeInfo,  '', false, false, false);
				</script>
</head>
<body>
<div id="breadcrumbs"></div>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td valign="top"><a name="Top"></a>
<div id="page-guid" value="1.839540980397304E-305"></div>
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td nowrap="true" class="pageTitle">指南：泛化关系</td><td width="100%">
<div id="contentPageToolbar" align="right"></div>
</td>
</tr>
</table>
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td class="pageTitleSeparator"><img height="1" title="" alt="" src="./../../../images/shim.gif"></td>
</tr>
</table>
<div class="overview">
<table cellpadding="0" cellspacing="0" border="0" width="97%">
<tr>
<td width="50"><img title="" alt="" src="./../../../images/guidance.gif"></td><td>
<table cellpadding="0" cellspacing="0" border="0" class="overviewTable">
<tr>
<td valign="top">泛化关系是获取不同的类之间的共同属性的类关系。本指南说明如何使用此关系。</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<div class="sectionHeading">关系</div>
<div class="sectionContent">
<table cellpadding="0" cellspacing="0" border="0" class="sectionTable">
<tr valign="top">
<th scope="row" class="sectionTableHeading">相关元素</th><td class="sectionTableCell">
<ul>
<li>
<a href="./../../../core.base_rup/roles/rup_designer_BA8DE74E.html" guid="{DB21F5EF-810B-4994-B120-79FA8774FA9D}">设计人员</a>
</li>
<li>
<a href="./../../../core.base_rup/tasks/class_design_98F20FF9.html" guid="{27AE0601-2E95-4A6A-8EB3-0A4BA8E5626B}">类设计</a>
</li>
<li>
<a href="./../../../core.base_rup/workproducts/rup_design_model_2830034D.html" guid="{8CDAEAD4-5E84-4F50-87FD-3240ED047DE7}">设计模型</a>
</li>
</ul>
</td>
</tr>
</table>
</div>
<div class="sectionHeading">主要描述</div>
<div class="sectionContent">
<table cellpadding="0" cellspacing="0" border="0" class="sectionTable">
<tr valign="top">
<td class="sectionTableSingleCell"><a id="Top" name="Top"></a><a id="XE_use-case-generalization__guidelines_for" name="XE_use-case-generalization__guidelines_for"></a><a id="XE_generalization__guidelines_for" name="XE_generalization__guidelines_for" class="index" key="泛化关系（generalization）" text="指南"></a> 
<h3>
    <a id="Generalization" name="Generalization">泛化关系</a>
</h3>
<p>
    在现实生活中的许多事物都有共同的属性。例如，狗和猫都是动物。对象也可以有共同的属性，您可以使用它们的类之间的泛化关系来阐明。 通过将共同的属性抽取到它们自己的类中，您将能在将来更容易地变更和维护系统。
</p>
<p>
    泛化关系显示一个类从另一个类继承。继承类称为后代。 被继承的类称为祖代。 继承意味着祖代的定义（包括任何特征，例如属性、关系或对其对象的操作）对于后代的对象也有效。 泛化关系是从后代类绘制到其祖代类的。
</p>
<p>
    泛化关系可以分几个阶段进行，这使您可以对复杂的、多层次的继承层次结构进行建模。 一般属性置于继承层次结构的上部，而特殊属性则置于下部。换言之，您可以使用泛化关系来对更一般概念的特化进行建模。
</p>
<p class="exampleheading">
    示例
</p>
<p class="example">
    在回收机系统中，所有的类（罐、瓶和箱）均描述不同类型的存放项。 除了属于同一类型之外，它们还有两个共同的属性：都具有高度和重量。 您可以通过属性和操作，在单独的类“存放项”中对这些属性进行建模。 罐、瓶和箱将继承这个类的属性。
</p>
<p class="picturecenter" align="center">
    <img src="./../../../core.base_rup/guidances/guidelines/resources/md_gene2.gif" width="400" height="275" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    罐、瓶和箱这几个类具有共同的属性，即高度和重量。每个属性都是一般概念“存放项”的特化。
</p>
<h3>
    <a id="XE_multiple_inheritance" name="XE_multiple_inheritance" class="index" key="多重继承"></a><a id="XE_multiple_inheritance__guidelines_for" name="XE_multiple_inheritance__guidelines_for" class="index" key="监视和控制（monitoring and control）" text="指南"></a><a id="XE_inheritance__multiple_inheritance" name="XE_inheritance__multiple_inheritance" class="index" key="继承（inheritance）" text="用于支持实施复用的继承"></a><a id="Multiple Inheritance" name="Multiple Inheritance">多重继承</a>
</h3>
<p>
    通过多重继承，一个类可以继承自其他几个类，尽管通常它将只继承自一个类。
</p>
<p>
    如果您使用多重继承，则必须知道几个潜在问题：
</p>
<ul>
    <li>
        如果一个类继承自几个类，则必须检查如何在祖代中命名关系、操作和属性。 如果几个祖代中出现同样的名称，则必须描述这对特定的继承类意味着什么；例如，通过限定名称来指出其声明的源。
    </li>
    <li>
        如果使用重复的继承；在这种情况下，一个后代将多次继承同一个祖代。 如果发生这种情况，则继承层次结构将为“菱形”，如下所示。
    </li>
</ul>
<p class="picturecenter" align="center">
    <img src="./../../../core.base_rup/guidances/guidelines/resources/md_gene3.gif" width="362" height="218" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    多重和重复继承。“带对话框的滚动窗口”类就多次继承“窗口”类。
</p>
<p>
    在此环境下，一个可能出现的问题是：“有多少‘窗口’属性的副本包含在‘带对话框的滚动窗口’的实例中？”因此，如果您在使用重复继承，则必须明确定义此语义；在大多数情况下，这将通过支持多重继承的编程语言来定义。
</p>
<p>
    通常，掌控多重继承的编程语言规则是复杂的，常常难以正确使用。所以，建议您只在需要时才使用多重继承，而且使用时始终要小心。
</p>
<h3>
    <a id="XE_concrete_classes__guidelines_for" name="XE_concrete_classes__guidelines_for" class="index" key="具体类（concrete classes）" text="指南"></a><a id="Abstract and Concrete Classes" name="Abstract and Concrete Classes">抽象类和具体类</a> <a id="XE_abstract_classes__guidelines_for" name="XE_abstract_classes__guidelines_for" class="index" key="抽象类（abstract classes）" text="指南"></a>
</h3>
<p>
    未进行实例化，而且其存在的目的只是供其他类继承，这样的类就是抽象类。 实际实例化的类是具体类。请注意，一个抽象类必须至少有一个后代才有用。
</p>
<p class="exampleheading">
    示例
</p>
<p class="example">
    “仓库处理系统”中的“集装箱地点”是一个抽象实体类，它代表不同类型的集装箱地点的共同属性。 该类由具体类“车站”、“运输机”和“存储单元”继承，这三个类均可充当仓库中的集装箱地点。
    所有这些对象都有一个共同属性：它们能容纳一个或多个集装箱。
</p>
<p class="picturecenter" align="center">
    <img src="./../../../core.base_rup/guidances/guidelines/resources/md_gene4.gif" width="370" height="208" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    被继承的类（此处为“集装箱地点”）是抽象的，其自身并未实例化。
</p>
<h3>
    <a id="Use" name="Use">使用</a>
</h3>
<p>
    因为类构造型有多种用途，所以从一个类构造型到另一个类构造型的继承并没有意义。 例如，如果让边界类继承实体类，则会使边界类成为某种混合体。所以，您应只在具有相同构造型的类之间使用泛化关系。
</p>
<p>
    可以使用泛化关系来表示类与类之间的两种关系：
</p>
<ul>
    <li>
        划分子类型，指定后代是祖代的子类型。 划分子类型意味着，后代继承了祖代的结构和行为，且后代是祖代的一种（即，后代是在任何情况下均可代替其所有祖代的子类型）。
    </li>
    <li>
        划分子类，指定后代是祖代的子类（但不是子类型）。 划分子类意味着，后代继承了祖代的结构和行为，但后代不是祖代的一种。
    </li>
</ul>
<p>
    您可以通过以下途径创建这样的关系：取出几个类的共同属性，并将这些属性放到一个单独的类中供其他类继承；或者创建一些将较一般的类特化的新类，并允许新类从一般类继承。
</p>
<p>
    如果这两种变体一致，那么您应该不难设置类之间的正确继承。 但在某些情况下，它们并不一致，您必须小心保持继承的使用可以让人理解。最起码您应知道模型中每个继承关系的用途。
</p>
<h3>
    <a id="XE_inheritance__to_support_polymorphism" name="XE_inheritance__to_support_polymorphism"></a><a id="XE_generalization__inheritance_to_support_polymorphism" name="XE_generalization__inheritance_to_support_polymorphism"></a><a id="Inheritance to Support Polymorphism" name="Inheritance to Support Polymorphism">用于支持多态性的继承</a>
</h3>
<p>
    划分子类型意味着，后代是在任何情况下均可代替其所有祖代的子类型。 划分子类型是多态性的特殊情况，且是一个重要属性，因为它允许您设计所有客户端（使用祖代的对象），而无需考虑祖代的潜在后代。
    这使得客户端对象更为普通且可复用。当客户端使用实际对象时，它将以特定方式工作，并将始终发现对象在执行任务。 划分子类型将确保系统能容忍子类型集中发生的变更。
</p>
<p class="exampleheading">
    示例
</p>
<p class="example">
    在“仓库处理系统”中，“运输机接口”类定义了用于与所有类型的运输装置（例如起重机和卡车）进行通信的基本功能。 该类定义了操作 executeTransport 及其他事项。
</p>
<p class="picturecenter" align="center">
    <img src="./../../../core.base_rup/guidances/guidelines/resources/md_gene5.gif" width="387" height="193" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    “卡车接口”和“起重机接口”类都继承自“运输机接口”；即，这两个类的对象将响应消息
    executeTransport。这些对象随时都可以代替“运输机接口”，并将提供其所有行为。这样，其他对象（客户端对象）可以发送消息给“运输机接口”对象，而无需知道“卡车接口”或“起重机接口”对象是否将响应此消息。
</p>
<p class="picturetext">
    “运输机接口”类甚至可以是抽象的，且其本身从不实例化。 在这种情况下，“运输机接口”可能只定义 executeTransport 操作的特征符，而由后代类来实施它。
</p>
<p>
    有些面向对象语言（例如 C++）使用类层次结构作为类型分层结构，迫使设计人员在设计模型中使用子类型的继承。 其他语言（例如 Smalltalk-80）在编译时不进行类型检查。如果对象不能响应接收到的消息，它们将生成一条错误消息。
</p>
<p>
    一个好主意是：即使在不进行类型检查的语言中，也使用泛化关系来表示子类型关系。 在某些情况下，应使用泛化关系来使对象模型和源代码更容易理解和维护，而无论语言是否支持。 继承的这种用法是否是好的行事方式，很大程度上取决于编程语言的约定。
</p>
<h3>
    <a id="XE_inheritance__to_support_implementation_reuse" name="XE_inheritance__to_support_implementation_reuse"></a><a id="XE_generalization__inheritance_to_support_implementation_reuse" name="XE_generalization__inheritance_to_support_implementation_reuse"></a><a id="Inheritance to Support Implementation Reuse" name="Inheritance to Support Implementation Reuse">用于支持实施复用的继承</a>
</h3>
<p>
    划分子类设定了泛化关系的复用方面。划分子类时，您考虑可以通过继承其他类定义的属性来复用实施的哪些部分。 划分子类节省了工作量，并允许您在实施特定类时复用代码。
</p>
<p class="exampleheading">
    示例
</p>
<p class="example">
    在 Smalltalk-80 类库中，类 Dictionary 继承了类 Set 的属性。
</p>
<p class="picturecenter" align="center">
    <img src="./../../../core.base_rup/guidances/guidelines/resources/md_gene6.gif" width="302" height="141" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    此泛化关系的存在的原因是，Dictionary 可以复用一些实施 Set 时所用的普通方法和存储策略。 即使 Dictionary 可以看作一个 Set（包含键－值对），但 Dictionary 不是 Set 的子类型，因为您无法向
    Dictionary 添加任何种类的对象（只能添加键－值对）。使用 Dictionary 的对象并不清楚 Dictionary 实际上是一个 Set。
</p>
<p>
    划分子类常常会导致产生不合逻辑的继承层次结构，这些继承层次结构难以理解和维护。 所以，除非在编程语言使用方面另有建议，否则建议您不要仅仅为了复用而使用继承。这种复用通常都难于维护。 类 Set 中的任何更改都可能意味着继承类 Set
    的所有类也要进行大量更改。请注意这一点，并且只继承稳定的类。 继承实际上将冻结类 Set 的实施，因为更改它的代价太大了。
</p>
<h3>
    <a id="XE_programming_languages__designing_inheritance" name="XE_programming_languages__designing_inheritance" class="index" key="编程语言（programming languages）" text="设计继承"></a><a id="XE_inheritance__in_programming_languages" name="XE_inheritance__in_programming_languages"></a><a id="XE_generalization__inheritance_in_programming_languages" name="XE_generalization__inheritance_in_programming_languages"></a><a id="Inheritance in Programming Languages" name="Inheritance in Programming Languages">编程语言中的继承</a>
</h3>
<p>
    在设计中使用泛化关系，这应在很大程度上取决于编程语言中继承的语义和建议用法。 面向对象语言支持类之间的继承，但非面向对象语言则不支持。您应控制设计模型中的语言特征。 如果您在使用不支持继承或多重继承的语言，则必须在实施时模拟继承。
    在这种情况下，您最好在设计模型中对该模拟进行建模，而不要使用泛化关系来描述继承结构。 如果使用泛化关系对继承结构建模，然后在实施时模拟继承，则会毁坏整个设计。
</p>
<p>
    如果您在使用不支持继承或多重继承的语言，则必须在实施时模拟继承。 在这种情况下，您最好在设计模型中对该模拟进行建模，而不要使用泛化关系来描述继承结构。 如果使用泛化关系对继承结构建模，然后只在实施时模拟继承，则会毁坏整个设计。
</p>
<p>
    在模拟期间，您将可能必须更改接口和其他对象属性。建议您按以下方式之一模拟继承：
</p>
<ol>
    <li>
        让后代转发消息给祖代。
    </li>
    <li>
        在每个后代中复制祖代的代码。在这种情况下，不创建任何祖代类。
    </li>
</ol>
<p class="exampleheading">
    示例
</p>
<p class="example">
    在此示例中，后代通过链接（它们是关联的实例）转发消息给祖代。
</p>
<p class="picturecenter" align="center">
    <img src="./../../../core.base_rup/guidances/guidelines/resources/md_gene7.gif" width="346" height="206" alt="附带文本中描述的图。" />
</p>
<p class="picturetext">
    将“罐”、“瓶”和“箱”对象的公共行为分配给一个特殊类。 必要时，拥有此公共行为的对象发送消息给“存放项”对象来执行该行为。
</p><br />
<br /></td>
</tr>
</table>
</div>
<table cellpadding="0" cellspacing="0" border="0" class="copyright">
<tr>
<td class="copyright"><p>
    &copy; &nbsp;Copyright IBM Corp.&nbsp;1987, 2006. &nbsp;All Rights Reserved.
</p></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
<script language="JavaScript" type="text/javascript">
				contentPage.onload();
			</script>
</html>
